package met.cs664.ai.cox.soc;

import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import soc.game.SOCGame;
import soc.message.SOCJoinGameAuth;
import soc.robot.SOCRobotBrain;
import soc.robot.SOCRobotClient;
import soc.util.CappedQueue;

import java.util.Hashtable;

/**
 * Basic robot extending from the robot client create by Robert S Thomas. The SOCRobotClient provides the interface, and
 * fundamental scaffolding for connecting, and interacting with the SOC server. It also creates the robot brains when
 * instructed by the server to join a game. The SOCRobotBrain is the heart of all decision making done by the robot
 * clients.
 *
 * This class overrides the join game message from the base robot client to supply the new robot with a Brain
 * implementation of the SOCRobotBrain. The Robot can be started using several different options used to specify
 * connection settings, and what aspects of the base SOCRobotBrain to override with our own implementation.
 *
 * @author mcox
 */
public class Robot extends SOCRobotClient {

    /** Startup options */
    private static Options options;

    /**
     * Optional and required options supplied at client startup and parsed using args4j
     * @author mcox
     * @since 2014/11/30
     */
    static class Options {
        @Option(name = "-h", aliases = {"--host"}, required = true, usage = "Address of the remote SOC server")
        public String host;

        @Option(name = "-p", aliases = {"--port"}, required = true, usage = "Port to connect to on remote SOC server")
        public int port;

        @Option(name = "-n", aliases = {"--nickname"}, required = true, usage = "The name of the agent connecting")
        public String nickname;

        @Option(name = "-pwd", aliases = {"--password"}, required = true, usage = "Password associated with the nickname")
        public String pass;

        @Option(name = "-oP", aliases = {"--placement"}, usage = "Override placement of initial settlements and roads")
        public boolean isPlacing;
    }

    /**
     * Create a new robot client supplying the base SOCRobotClient with required connection parameters
     * @param host The remote address of the host of the SOC server
     * @param port Port on the remote host to connect to
     * @param nickname Nickname of the robot connecting
     * @param pass Password for the nickname (not used)
     */
    public Robot(String host, int port, String nickname, String pass) {
        super(host, port, nickname, pass);
    }

    /**
     * Load options from the commandline and kick off our robot.
     * @param args parsed using args4j
     */
    public static void main(String [] args) {
        options = new Options();
        CmdLineParser parser = new CmdLineParser(options);

        try {
            parser.parseArgument(args);
        } catch (CmdLineException e) {
            parser.printUsage(System.err);
            System.exit(1);
        }

        Robot agent = new Robot(options.host, options.port, options.nickname, options.pass);
        agent.init();
    }

    /**
     * Overrides the join game from SOCRobotClient with our own brain in place of SOCRobotBrain
     * @param mes Join game message.
     */
    @Override
    protected void handleJOINGAMEAUTH(SOCJoinGameAuth mes) {
        gamesPlayed++;

        final String gaName = mes.getGame();

        SOCGame ga = new SOCGame(gaName, true, (Hashtable) gameOptions.get(gaName));
        games.put(gaName, ga);

        CappedQueue brainQ = new CappedQueue();
        brainQs.put(gaName, brainQ);

        SOCRobotBrain rb = new Brain(this, currentRobotParameters, ga, brainQ).placeInitialSettlements(options.isPlacing);
        robotBrains.put(gaName, rb);
    }
}
